﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace SerialTool
{
    public partial class FormMain : Form
    {

        delegate void ShowFrameHandler(Frame frame);

        SerialPort serialPort = new SerialPort();
        FrameManager frameManager;
        byte[] txBuffer = new byte[2048*16];
        byte[] txData=new byte[2048*16];
        int framecount = 0;
        int txLength = 0;


        public FormMain()
        {
            InitializeComponent();

            frameManager = new FrameManager(serialPort);

            frameManager.AddFilter(new FrameFilter(this));

        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            toolStripComboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
            string[] ports = SerialPort.GetPortNames();
            if (ports != null)
            {
                for (int i = 0; i < ports.Length; i++)
                {
                    toolStripComboBox1.Items.Add(ports[i]);
                }
            }
            if (toolStripComboBox1.Items.Count > 0)
            {
                toolStripComboBox1.SelectedIndex = 0;
            }

            groupBox1.Enabled = false;
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                try
                {
                    serialPort.Close();
                    buttonStart.Text = "打开";
                    toolStripComboBox1.Enabled = true;
                    buttonStart.Image = Properties.Resources.Play;
                    groupBox1.Enabled = false;
                }
                catch { }
            }
            else
            {
                try
                {
                    serialPort.PortName = toolStripComboBox1.Text;
                    serialPort.BaudRate = 115200;
                    serialPort.Open();
                    buttonStart.Text = "关闭";
                    toolStripComboBox1.Enabled = false;
                    buttonStart.Image = Properties.Resources.Stop;
                    groupBox1.Enabled = true;
                }
                catch(Exception ex) {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            textBoxRx.Clear();
        }

        public void ShowFrame(Frame frame)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new ShowFrameHandler(ShowFrame), new object[] { frame });
            }
            else
            {
                revCmd = frame.Cmd;
                byte[] data = frame.RawData;
                revIndex = (short)(data[10] + data[11] * 256);

                framecount++;
                textBoxRx.AppendText(framecount.ToString().PadRight(5, ' ') + ">" + frame.ToString());
                textBoxRx.AppendText("\r\n");
            }
        }

        void TransmiteFrame(byte[] data, int length)
        {

            if (length <= 0) return;
            int dataLen = length + 2;


            //计算CRC
            txBuffer[0] = (byte)((dataLen >> 8) & 0xff);
            txBuffer[1] = (byte)(dataLen & 0xff);

            for (int i = 0; i < length; i++)
            {
                txBuffer[i + 2] = data[i];
            }

            UInt16 crc = CRC16.ComputeCRC16(txBuffer, 0, dataLen);

            int index = 0;

            //帧头
            txBuffer[index] = 0x10;
            index++;
            txBuffer[index] = 0x02;
            index++;


            //数据长度
            txBuffer[index] = (byte)((dataLen >> 8) & 0xff);
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            txBuffer[index] = (byte)(dataLen & 0xff);
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            //数据
            for (int i = 0; i < length; i++)
            {
                txBuffer[index] = data[i];
                index++;
                if (txBuffer[index - 1] == 0x10)
                {
                    txBuffer[index] = 0x10;
                    index++;
                }
            }
            //CRC
            txBuffer[index] = (byte)((crc >> 8) & 0xff);
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            txBuffer[index] = (byte)(crc & 0xff);
            index++;
            if (txBuffer[index - 1] == 0x10)
            {
                txBuffer[index] = 0x10;
                index++;
            }
            //帧尾
            txBuffer[index] = 0x10;
            index++;
            txBuffer[index] = 0x03;
            index++;


            

            if (serialPort.IsOpen)
            {
                try
                {
                    //发送数据
                    serialPort.Write(txBuffer, 0, index);
                }
                catch (Exception) { }
            }
        }

        private void buttonSend_Click(object sender, EventArgs e)
        {
            mytime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
                                        DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);

            PrepareData(true);
            
            TransmiteFrame(txData, txLength);
        }

        private void PrepareData(bool addSTS)
        {
            int len = 0;
            txData[len++] = byte.Parse(textBox2_sourceAddr.Text, System.Globalization.NumberStyles.AllowHexSpecifier); //源端口 (测试仪)
            txData[len++] = 0;//源地址长度
            txData[len++] = byte.Parse(textBox3_targetAddr.Text, System.Globalization.NumberStyles.AllowHexSpecifier); //目的端口号 (记录板)
            txData[len++] = 0; //目的地址长度

            txData[len++] = byte.Parse(textBox4_type.Text, System.Globalization.NumberStyles.AllowHexSpecifier);//业务类型
            txData[len++] = byte.Parse(textBox5_CMD.Text, System.Globalization.NumberStyles.AllowHexSpecifier);//命令


            string[] dataStr = textBox6_data.Text.Split(new char[] {' ','\t','\r','\n' }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < dataStr.Length; i++)
            {
                txData[len++] = byte.Parse(dataStr[i], System.Globalization.NumberStyles.AllowHexSpecifier);
            }

            if (checkBox_STS.Checked && addSTS)
            {
                byte[] sts = CreatSts();
                for (int i = 0; i < sts.Length; i++)
                {
                    txData[len++] = sts[i];
                }
            }
            txLength = len;
        }

        #region 实时帧

        #region 变量

        DateTime mytime;
        const string stsCMD = "50";//十六进制
        const string stsCMDACK = "60";//十六进制
        const string anaCMD = "51";//十六进制
        const string anaCMDACK = "61";//十六进制
        const string powCMD = "F0";//十六进制
        const string powCMDACK = "F0";//十六进制
        const string timerPeriod = "100";
        int waitcount = 0;
        byte revCmd = 0x00;
        short revIndex = 0x00;
        byte sendCmd = 0;
        short stsIndex = 0;
        int anaSize = 0;
        DateTime[] anaTime = new DateTime[100];
        short anaIndex = 0;
        int powSize = 0;
        short powIndex = 0;
        byte XHJ_Light = 0x01;

        #region [244]  I_II_SX_XX
        byte I_II_SX_XX = 0x16; //默认:有绝缘节、上行、I端
        byte I_II_SX_XX_bitI_IIlock = 0x80;
        byte I_II_SX_XX_bitSXX_H = 0x40;
        byte I_II_SX_XX_bitI_II_H = 0x20;
        byte I_II_SX_XX_bitJY = 0x10;
        byte I_II_SX_XX_bitII = 0x08;
        byte I_II_SX_XX_bitI = 0x04;
        byte I_II_SX_XX_bitSX = 0x02;
        byte I_II_SX_XX_bitXX = 0x01;
        #endregion

        #region AB机 库内　速度码
        byte A_B_ji = 0x11;
        byte A_B_ji_kunei = 0x80;
        byte A_B_ji_ABhun = 0x40;
        byte A_B_ji_B     = 0x10;
        byte A_B_ji_A     = 0x08;
        byte A_B_ji_SD3   = 0x04;
        byte A_B_ji_SD2   = 0x02;
        byte A_B_ji_SD1   = 0x01;
        #endregion

        uint kilometerPost = 0;
        #endregion

        #region bit operation
        byte setbit(byte data, byte bit)
        {
            return (byte)(data | bit);
        }
        byte clsbit(byte data, byte bit)
        {
            return (byte)(data & (~bit));
        }
        bool havebit(byte data, byte bit)
        {
            if ((byte)(data & bit) == bit)
                return true;
            else
                return false;
        }
        #endregion

        #region start
        private void button_JLB_Click(object sender, EventArgs e)
        {
            if (button_JLB.Text == "发送实时帧")
            {
                button_JLB.BackColor = Color.Red;
                button_JLB.Text = "停止发送";
                textBox1.Text = timerPeriod;
                textBox7.Text = "999999";

                textBox2_sourceAddr.Text = "20";
                textBox3_targetAddr.Text = "60";
                textBox4_type.Text = "01";
                textBox5_CMD.Text = stsCMD;
                textBox6_data.Text = "88 00 DC 02 00 00 02 01 00";

                checkBox_STS.Checked = true;
                checkBox_timer.Checked = true;
            }
            else
            {
                button_JLB.BackColor = Color.Green;
                button_JLB.Text = "发送实时帧";
                checkBox_STS.Checked = false;
                checkBox_timer.Checked = false;
            }

        }
        #endregion

        #region 增加一个波形
        private void button_ana_Click(object sender, EventArgs e)
        {
            anaSize += 183 * 1024;
            anaTime[(anaSize - (anaSize % (183 * 1024))) / (183 * 1024)] = DateTime.Now;
        }
        #endregion

        #region 增加一个掉电记录
        private void button_pow_Click(object sender, EventArgs e)
        {
            powSize += 16;
        }
        #endregion

        #region read SD

        private void button_R_SD_I_Click(object sender, EventArgs e)
        {
            textBox2_sourceAddr.Text = "20";
            textBox3_targetAddr.Text = "60";
            textBox4_type.Text = "01";
            textBox5_CMD.Text = "F1";
            textBox6_data.Text = "88 00 DC 02 00 00 00 00";

            checkBox_STS.Checked = true;
            checkBox_timer.Checked = false;

            buttonSend_Click(null, null);

        }

        private void button_R_SD_A_Click(object sender, EventArgs e)
        {
            textBox2_sourceAddr.Text = "20";
            textBox3_targetAddr.Text = "60";
            textBox4_type.Text = "01";
            textBox5_CMD.Text = "F1";
            textBox6_data.Text = "55 00 DC 02 00 00 00 00";

            checkBox_STS.Checked = true;
            checkBox_timer.Checked = false;

            buttonSend_Click(null, null);
        }

        #endregion

        #region XHJ ligth
        private void button_L_Click(object sender, EventArgs e)
        {
            if (!checkBox_LEDhun.Checked)
            {
                button_L.BackColor = Color.Green;
                button_LU.BackColor = Color.Gray;
                button_U.BackColor = Color.Gray;
                button_U2.BackColor = Color.Gray;
                button_UU.BackColor = Color.Gray;
                button_HU.BackColor = Color.Gray;
                button_H.BackColor = Color.Gray;
                button_B.BackColor = Color.Gray;
                button_flash.BackColor = Color.Gray;
                XHJ_Light = 0x01;
            }
            else
            {
                if (button_L.BackColor != Color.Gray)
                {
                    button_L.BackColor = Color.Gray;
                }
                else
                {
                    button_L.BackColor = Color.Green;
                }
                int count = 0;
                if (button_L.BackColor != Color.Gray)
                    count++;
                if (button_LU.BackColor != Color.Gray)
                    count++;
                if (button_U.BackColor != Color.Gray)
                    count++;
                if (button_U2.BackColor != Color.Gray)
                    count++;
                if (button_UU.BackColor != Color.Gray)
                    count++;
                if (button_HU.BackColor != Color.Gray)
                    count++;
                if (button_H.BackColor != Color.Gray)
                    count++;
                if (button_B.BackColor != Color.Gray)
                    count++;
                if (count > 1)
                    XHJ_Light = (byte)(XHJ_Light | 0x40);
            }
        }

        private void button_LU_Click(object sender, EventArgs e)
        {
            if (!checkBox_LEDhun.Checked)
            {
                button_L.BackColor = Color.Gray;
                button_LU.BackColor = Color.YellowGreen;
                button_U.BackColor = Color.Gray;
                button_U2.BackColor = Color.Gray;
                button_UU.BackColor = Color.Gray;
                button_HU.BackColor = Color.Gray;
                button_H.BackColor = Color.Gray;
                button_B.BackColor = Color.Gray;
                button_flash.BackColor = Color.Gray;
                XHJ_Light = 0x02;
            }
            else
            {
                if (button_LU.BackColor != Color.Gray)
                {
                    button_LU.BackColor = Color.Gray;
                }
                else
                {
                    button_LU.BackColor = Color.YellowGreen;
                }
                int count = 0;
                if (button_L.BackColor != Color.Gray)
                    count++;
                if (button_LU.BackColor != Color.Gray)
                    count++;
                if (button_U.BackColor != Color.Gray)
                    count++;
                if (button_U2.BackColor != Color.Gray)
                    count++;
                if (button_UU.BackColor != Color.Gray)
                    count++;
                if (button_HU.BackColor != Color.Gray)
                    count++;
                if (button_H.BackColor != Color.Gray)
                    count++;
                if (button_B.BackColor != Color.Gray)
                    count++;
                if (count > 1)
                    XHJ_Light = (byte)(XHJ_Light | 0x40);
            }
        }

        private void button_U_Click(object sender, EventArgs e)
        {
            if (!checkBox_LEDhun.Checked)
            {
                button_L.BackColor = Color.Gray;
                button_LU.BackColor = Color.Gray;
                button_U.BackColor = Color.Yellow;
                button_U2.BackColor = Color.Gray;
                button_UU.BackColor = Color.Gray;
                button_HU.BackColor = Color.Gray;
                button_H.BackColor = Color.Gray;
                button_B.BackColor = Color.Gray;
                button_flash.BackColor = Color.Gray;
                XHJ_Light = 0x03;
            }
            else
            {
                if (button_U.BackColor != Color.Gray)
                {
                    button_U.BackColor = Color.Gray;
                }
                else
                {
                    button_U.BackColor = Color.Yellow;
                }
                int count = 0;
                if (button_L.BackColor != Color.Gray)
                    count++;
                if (button_LU.BackColor != Color.Gray)
                    count++;
                if (button_U.BackColor != Color.Gray)
                    count++;
                if (button_U2.BackColor != Color.Gray)
                    count++;
                if (button_UU.BackColor != Color.Gray)
                    count++;
                if (button_HU.BackColor != Color.Gray)
                    count++;
                if (button_H.BackColor != Color.Gray)
                    count++;
                if (button_B.BackColor != Color.Gray)
                    count++;
                if (count > 1)
                    XHJ_Light = (byte)(XHJ_Light | 0x40);
            }
        }

        private void button_U2_Click(object sender, EventArgs e)
        {
            if (!checkBox_LEDhun.Checked)
            {
                button_L.BackColor = Color.Gray;
                button_LU.BackColor = Color.Gray;
                button_U.BackColor = Color.Gray;
                button_U2.BackColor = Color.Yellow;
                button_UU.BackColor = Color.Gray;
                button_HU.BackColor = Color.Gray;
                button_H.BackColor = Color.Gray;
                button_B.BackColor = Color.Gray;
                XHJ_Light = (byte)(0x04 | (XHJ_Light & 0x80));
            }
            else
            {
                if (button_U2.BackColor != Color.Gray)
                {
                    button_U2.BackColor = Color.Gray;
                }
                else
                {
                    button_U2.BackColor = Color.Yellow;
                }
                int count = 0;
                if (button_L.BackColor != Color.Gray)
                    count++;
                if (button_LU.BackColor != Color.Gray)
                    count++;
                if (button_U.BackColor != Color.Gray)
                    count++;
                if (button_U2.BackColor != Color.Gray)
                    count++;
                if (button_UU.BackColor != Color.Gray)
                    count++;
                if (button_HU.BackColor != Color.Gray)
                    count++;
                if (button_H.BackColor != Color.Gray)
                    count++;
                if (button_B.BackColor != Color.Gray)
                    count++;
                if (count > 1)
                    XHJ_Light = (byte)(XHJ_Light | 0x40);
            }
        }

        private void button_UU_Click(object sender, EventArgs e)
        {
            if (!checkBox_LEDhun.Checked)
            {
                button_L.BackColor = Color.Gray;
                button_LU.BackColor = Color.Gray;
                button_U.BackColor = Color.Gray;
                button_U2.BackColor = Color.Gray;
                button_UU.BackColor = Color.Yellow;
                button_HU.BackColor = Color.Gray;
                button_H.BackColor = Color.Gray;
                button_B.BackColor = Color.Gray;
                XHJ_Light = (byte)(0x06 | (XHJ_Light & 0x80));
            }
            else
            {
                if (button_UU.BackColor != Color.Gray)
                {
                    button_UU.BackColor = Color.Gray;
                }
                else
                {
                    button_UU.BackColor = Color.Yellow;
                }
                int count = 0;
                if (button_L.BackColor != Color.Gray)
                    count++;
                if (button_LU.BackColor != Color.Gray)
                    count++;
                if (button_U.BackColor != Color.Gray)
                    count++;
                if (button_U2.BackColor != Color.Gray)
                    count++;
                if (button_UU.BackColor != Color.Gray)
                    count++;
                if (button_HU.BackColor != Color.Gray)
                    count++;
                if (button_H.BackColor != Color.Gray)
                    count++;
                if (button_B.BackColor != Color.Gray)
                    count++;
                if (count > 1)
                    XHJ_Light = (byte)(XHJ_Light | 0x40);
            }
        }

        private void button_HU_Click(object sender, EventArgs e)
        {
            if (!checkBox_LEDhun.Checked)
            {
                button_L.BackColor = Color.Gray;
                button_LU.BackColor = Color.Gray;
                button_U.BackColor = Color.Gray;
                button_U2.BackColor = Color.Gray;
                button_UU.BackColor = Color.Gray;
                button_HU.BackColor = Color.OrangeRed;
                button_H.BackColor = Color.Gray;
                button_B.BackColor = Color.Gray;
                XHJ_Light = (byte)(0x05 | (XHJ_Light & 0x80));
            }
            else
            {
                if (button_HU.BackColor != Color.Gray)
                {
                    button_HU.BackColor = Color.Gray;
                }
                else
                {
                    button_HU.BackColor = Color.OrangeRed;
                }
                int count = 0;
                if (button_L.BackColor != Color.Gray)
                    count++;
                if (button_LU.BackColor != Color.Gray)
                    count++;
                if (button_U.BackColor != Color.Gray)
                    count++;
                if (button_U2.BackColor != Color.Gray)
                    count++;
                if (button_UU.BackColor != Color.Gray)
                    count++;
                if (button_HU.BackColor != Color.Gray)
                    count++;
                if (button_H.BackColor != Color.Gray)
                    count++;
                if (button_B.BackColor != Color.Gray)
                    count++;
                if (count > 1)
                    XHJ_Light = (byte)(XHJ_Light | 0x40);
            }
        }

        private void button_H_Click(object sender, EventArgs e)
        {
            if (!checkBox_LEDhun.Checked)
            {
                button_L.BackColor = Color.Gray;
                button_LU.BackColor = Color.Gray;
                button_U.BackColor = Color.Gray;
                button_U2.BackColor = Color.Gray;
                button_UU.BackColor = Color.Gray;
                button_HU.BackColor = Color.Gray;
                button_H.BackColor = Color.Red;
                button_B.BackColor = Color.Gray;
                button_flash.BackColor = Color.Gray;
                XHJ_Light = 0x07;
            }
            else
            {
                if (button_H.BackColor != Color.Gray)
                {
                    button_H.BackColor = Color.Gray;
                }
                else
                {
                    button_H.BackColor = Color.Red;
                }
                int count = 0;
                if (button_L.BackColor != Color.Gray)
                    count++;
                if (button_LU.BackColor != Color.Gray)
                    count++;
                if (button_U.BackColor != Color.Gray)
                    count++;
                if (button_U2.BackColor != Color.Gray)
                    count++;
                if (button_UU.BackColor != Color.Gray)
                    count++;
                if (button_HU.BackColor != Color.Gray)
                    count++;
                if (button_H.BackColor != Color.Gray)
                    count++;
                if (button_B.BackColor != Color.Gray)
                    count++;
                if (count > 1)
                    XHJ_Light = (byte)(XHJ_Light | 0x40);
            }
        }

        private void button_B_Click(object sender, EventArgs e)
        {
            if (!checkBox_LEDhun.Checked)
            {
                button_L.BackColor = Color.Gray;
                button_LU.BackColor = Color.Gray;
                button_U.BackColor = Color.Gray;
                button_U2.BackColor = Color.Gray;
                button_UU.BackColor = Color.Gray;
                button_HU.BackColor = Color.Gray;
                button_H.BackColor = Color.Gray;
                button_B.BackColor = Color.White;
                button_flash.BackColor = Color.Gray;
                XHJ_Light = 0x08;
            }
            else
            {
                if (button_B.BackColor != Color.Gray)
                {
                    button_B.BackColor = Color.Gray;
                }
                else
                {
                    button_B.BackColor = Color.White;
                }
                int count = 0;
                if (button_L.BackColor != Color.Gray)
                    count++;
                if (button_LU.BackColor != Color.Gray)
                    count++;
                if (button_U.BackColor != Color.Gray)
                    count++;
                if (button_U2.BackColor != Color.Gray)
                    count++;
                if (button_UU.BackColor != Color.Gray)
                    count++;
                if (button_HU.BackColor != Color.Gray)
                    count++;
                if (button_H.BackColor != Color.Gray)
                    count++;
                if (button_B.BackColor != Color.Gray)
                    count++;
                if (count > 1)
                    XHJ_Light = (byte)(XHJ_Light | 0x40);
            }
        }

        private void button_flash_Click(object sender, EventArgs e)
        {
            if ((XHJ_Light & 0x80) == 0x80)
            {
                button_flash.BackColor = Color.Gray;
                XHJ_Light = (byte)(XHJ_Light & 0x7F);
            }
            else if (XHJ_Light == 0x04 || XHJ_Light == 0x05 || XHJ_Light == 0x06)
            {
                XHJ_Light = (byte)(XHJ_Light | 0x80);
                button_flash.BackColor = Color.Red;
            }
        }

        private void button_lightOff_Click(object sender, EventArgs e)
        {
            button_L.BackColor = Color.Gray;
            button_LU.BackColor = Color.Gray;
            button_U.BackColor = Color.Gray;
            button_U2.BackColor = Color.Gray;
            button_UU.BackColor = Color.Gray;
            button_HU.BackColor = Color.Gray;
            button_H.BackColor = Color.Gray;
            button_B.BackColor = Color.Gray;
            button_flash.BackColor = Color.Gray;
            XHJ_Light = 0;
        }
        #endregion

        #region SX/XX 上下行
        private void button_SX_Click(object sender, EventArgs e)
        {
            if (checkBox_SXXhun.Checked)
            {
                if (button_SX.BackColor == Color.Green)
                {
                    button_SX.BackColor = Color.Gray;
                    I_II_SX_XX = clsbit(I_II_SX_XX, (byte)(I_II_SX_XX_bitSX | I_II_SX_XX_bitSXX_H));//去上行位　去混线位
                }
                else
                {
                    button_SX.BackColor = Color.Green;
                    I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitSX);//加上行位
                    if (havebit(I_II_SX_XX, I_II_SX_XX_bitXX))//有下行位
                        I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitSXX_H);//加混线位
                }
            }
            else
            {
                I_II_SX_XX = clsbit(I_II_SX_XX, I_II_SX_XX_bitSXX_H);//去混线位
                button_SX.BackColor = Color.Green;
                button_XX.BackColor = Color.Gray;
                I_II_SX_XX = clsbit(I_II_SX_XX, I_II_SX_XX_bitXX);//去下行位
                I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitSX);//加上行位
            }
        }

        private void button_XX_Click(object sender, EventArgs e)
        {
            if (checkBox_SXXhun.Checked)
            {
                if (button_XX.BackColor == Color.Green)
                {
                    button_XX.BackColor = Color.Gray;
                    I_II_SX_XX = clsbit(I_II_SX_XX, (byte)(I_II_SX_XX_bitXX | I_II_SX_XX_bitSXX_H));//去下行位　去混线位
                }
                else
                {
                    button_XX.BackColor = Color.Green;
                    I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitXX);//加下行位
                    if (havebit(I_II_SX_XX, I_II_SX_XX_bitSX))//有上行位
                        I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitSXX_H);//加混线位
                }
            }
            else
            {
                I_II_SX_XX = clsbit(I_II_SX_XX, I_II_SX_XX_bitSXX_H);//去混线位
                button_XX.BackColor = Color.Green;
                button_SX.BackColor = Color.Gray;
                I_II_SX_XX = clsbit(I_II_SX_XX, I_II_SX_XX_bitSX);//去上行位
                I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitXX);//加下行位
            }
        }
        #endregion

        #region I/II 端
        private void button_ID_Click(object sender, EventArgs e)
        {
            if (checkBox_I_IIhun.Checked)
            {
                if (button_ID.BackColor == Color.Green)
                {
                    button_ID.BackColor = Color.Gray;
                    I_II_SX_XX = clsbit(I_II_SX_XX, (byte)(I_II_SX_XX_bitI | I_II_SX_XX_bitI_II_H));//去I端位　去混线位
                }
                else
                {
                    button_ID.BackColor = Color.Green;
                    I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitI);//加I端位
                    if (havebit(I_II_SX_XX, I_II_SX_XX_bitII))//有II端位
                        I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitI_II_H);//加混线位
                }
            }
            else
            {
                I_II_SX_XX = clsbit(I_II_SX_XX, I_II_SX_XX_bitI_II_H);//去混线位
                button_ID.BackColor = Color.Green;
                button_IID.BackColor = Color.Gray;
                I_II_SX_XX = clsbit(I_II_SX_XX, I_II_SX_XX_bitII);//去II端位
                I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitI);//加I端位
            }
        }

        private void button_IID_Click(object sender, EventArgs e)
        {
            if (checkBox_I_IIhun.Checked)
            {
                if (button_IID.BackColor == Color.Green)
                {
                    button_IID.BackColor = Color.Gray;
                    I_II_SX_XX = clsbit(I_II_SX_XX, (byte)(I_II_SX_XX_bitII | I_II_SX_XX_bitI_II_H));//去II端位　去混线位
                }
                else
                {
                    button_IID.BackColor = Color.Green;
                    I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitII);//加II端位
                    if (havebit(I_II_SX_XX, I_II_SX_XX_bitI))//有I端位
                        I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitI_II_H);//加混线位
                }
            }
            else
            {
                I_II_SX_XX = clsbit(I_II_SX_XX, I_II_SX_XX_bitI_II_H);//去混线位
                button_IID.BackColor = Color.Green;
                button_ID.BackColor = Color.Gray;
                I_II_SX_XX = clsbit(I_II_SX_XX, I_II_SX_XX_bitI);//去I端位
                I_II_SX_XX = setbit(I_II_SX_XX, I_II_SX_XX_bitII);//加II端位
            }
        }
        #endregion

        #region A/B 机
        private void button_AJ_Click(object sender, EventArgs e)
        {
            if (checkBox_ABhun.Checked)
            {
                if (button_AJ.BackColor == Color.Green)
                {
                    button_AJ.BackColor = Color.Gray;
                    A_B_ji = clsbit(A_B_ji, (byte)(A_B_ji_A | A_B_ji_ABhun));//去A机位　去混线位
                }
                else
                {
                    button_AJ.BackColor = Color.Green;
                    A_B_ji = setbit(A_B_ji, A_B_ji_A);//加A机位
                    if (havebit(A_B_ji, A_B_ji_B))//有B机位
                        A_B_ji = setbit(A_B_ji, A_B_ji_ABhun);//加混线位
                }
            }
            else
            {
                A_B_ji = clsbit(A_B_ji, A_B_ji_ABhun);//去混线位
                button_AJ.BackColor = Color.Green;
                button_BJ.BackColor = Color.Gray;
                A_B_ji = clsbit(A_B_ji, A_B_ji_B);//去B机位
                A_B_ji = setbit(A_B_ji, A_B_ji_A);//加A机位
            }
        }

        private void button_BJ_Click(object sender, EventArgs e)
        {
            if (checkBox_ABhun.Checked)
            {
                if (button_BJ.BackColor == Color.Green)
                {
                    button_BJ.BackColor = Color.Gray;
                    A_B_ji = clsbit(A_B_ji, (byte)(A_B_ji_B | A_B_ji_ABhun));//去B机位　去混线位
                }
                else
                {
                    button_BJ.BackColor = Color.Green;
                    A_B_ji = setbit(A_B_ji, A_B_ji_B);//加B机位
                    if (havebit(A_B_ji, A_B_ji_A))//有A机位
                        A_B_ji = setbit(A_B_ji, A_B_ji_ABhun);//加混线位
                }
            }
            else
            {
                A_B_ji = clsbit(A_B_ji, A_B_ji_ABhun);//去混线位
                button_BJ.BackColor = Color.Green;
                button_AJ.BackColor = Color.Gray;
                A_B_ji = clsbit(A_B_ji, A_B_ji_A);//去A机位
                A_B_ji = setbit(A_B_ji, A_B_ji_B);//加B机位
            }
        }
        #endregion

        #region power
        private void textBox_pwr_TextChanged(object sender, EventArgs e)
        {
            checkBox_timer.Checked = false;
        }
        #endregion

        private byte[] CreatSts()
        {
            #region default
            byte[] res = new byte[256] { 
                0xAA, 0x55, 0xB1, 0xA1, 0x38, 0xEC, 0xDA, 0x42, 0x00, 0x00, 0x3F, 0xB6, 0x07, 0xBA, 0xB9, 0xB8,
                0x05, 0x00, 0xBA, 0x06, 0xC0, 0xB9, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x06,
                0x00, 0x00, 0xBA, 0xB5, 0xB5, 0x24, 0x08, 0x04, 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01,
                0x00, 0x00, 0xBF, 0xB3, 0x3A, 0x40, 0x04, 0xCE, 0x09, 0xF8, 0x08, 0x04, 0x01, 0x01, 0x01, 0x01,
                0x00, 0x00, 0x2B, 0x00, 0x3B, 0x04, 0x06, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x03,
                0x00, 0xC8, 0x08, 0x04, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x23, 0x00, 0x3B, 0x04, 0x07, 0x01,
                0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x03, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04,
                0x01, 0x01, 0x00, 0x00, 0x02, 0x80, 0x01, 0x01, 0x00, 0x00, 0xBF, 0xB3, 0x3A, 0xC0, 0x04, 0x4E,
                0x09, 0xF8, 0x08, 0x04, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x2A, 0x00, 0x3B, 0x04, 0xC6, 0x00,
                0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x03, 0x00, 0xC8, 0x08, 0x04, 0x01, 0x01, 0x01, 0x01,
                0x00, 0x00, 0x26, 0x00, 0x3B, 0x04, 0xBF, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x03,
                0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6E, 0x6F, 0x6F,
                0x6F, 0x6F, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xD0, 0xBD, 0xDA, 0x42, 0x00, 0x90, 0x02, 0x06,
                0x81, 0x72, 0x01, 0x02, 0x32, 0x03, 0x80, 0x00, 0x00, 0xC0, 0x02, 0x07, 0xB8, 0x1B, 0x00, 0x00,
                0xCF, 0x05, 0x01, 0x20, 0x20, 0x20, 0x20, 0x00, 0x02, 0x00, 0x12, 0x84, 0x00, 0xF3, 0x00, 0x00,
                0x00, 0x00, 0x08, 0x81, 0x16, 0x11, 0x82, 0xF5, 0x24, 0x00, 0xCC, 0xD2, 0x24, 0x00, 0x0C, 0xAF
            };
            #endregion


            #region time: offset [0x04 - 0x07] 4 - 7
            uint time = (uint)(
                        ((mytime.Year - 2000) << 26) |
                        (mytime.Month << 22) |
                        (mytime.Day << 17) |
                        (mytime.Hour << 12) |
                        (mytime.Minute << 06) |
                        (mytime.Second << 0));
            res[4 + 0] = (byte)(time >> 0);
            res[4 + 1] = (byte)(time >> 8);
            res[4 + 2] = (byte)(time >> 16);
            res[4 + 3] = (byte)(time >> 24);
            #endregion

            #region power: offset [0xB6 - 0xBF] 182 - 191
            for (int i = 0; i < 10; i++)
                res[182 + i] = byte.Parse(textBox_pwr.Text);
            #endregion

            #region kilo meter post: offset [0xD4 - 0xD6] 212 - 214
            res[212 + 0] = (byte)(kilometerPost >> 0);
            res[212 + 1] = (byte)(kilometerPost >> 8);
            res[212 + 2] = (byte)(kilometerPost >> 16);
            kilometerPost++;
            #endregion

            #region light: offset [0xF2] 242
            res[242 + 0] = XHJ_Light;
            #endregion

            #region SX/XX I/II: offset [0xF4] 244
            res[244 + 0] = I_II_SX_XX;
            #endregion

            #region A/B 机:offset [0xF5] 245
            res[245 + 0] = A_B_ji;
            #endregion
            return res;
        }

        #endregion

        #region timer
        int needSendCount = 0;

        private void checkBox_timer_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_timer.Checked)
            {
                revCmd = 0;
                revIndex = 0;
                sendCmd = 0;
                mytime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
                                        DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);


                needSendCount = int.Parse(textBox7.Text);
                timer1.Interval = int.Parse(textBox1.Text);
                timer1.Enabled = true;
                buttonSend.Enabled = false;
            }
            else
            {
                timer1.Enabled = false;
                buttonSend.Enabled = true;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (needSendCount <= 0)
            {
                timer1.Enabled = false;
                buttonSend.Enabled = true;
                checkBox_timer.Checked = false;
            }
            else
            {
                needSendCount--;

                if (!checkBox_STS.Checked)//不需要发送实时帧，这个时候也不会发波形和掉电帧
                {
                    PrepareData(true);
                    TransmiteFrame(txData, txLength);
                }
                else
                {
                    if (sendCmd != 0)
                    {
                        #region wait acknowledge and resend
                        
                        int stscmd      = byte.Parse(stsCMD, System.Globalization.NumberStyles.AllowHexSpecifier);
                        int stscmdack   = byte.Parse(stsCMDACK, System.Globalization.NumberStyles.AllowHexSpecifier);
                        int anacmd      = byte.Parse(anaCMD, System.Globalization.NumberStyles.AllowHexSpecifier);
                        int anacmdack   = byte.Parse(anaCMDACK, System.Globalization.NumberStyles.AllowHexSpecifier);
                        int powcmd      = byte.Parse(powCMD, System.Globalization.NumberStyles.AllowHexSpecifier);
                        int powcmdack   = byte.Parse(powCMDACK, System.Globalization.NumberStyles.AllowHexSpecifier);
                        waitcount++;
                        if (
                            (sendCmd == stscmd && revCmd == stscmdack) ||
                            (sendCmd == anacmd && revCmd == anacmdack) ||
                            (sendCmd == powcmd && revCmd == powcmdack)
                            )//&&revIndex == sendIndex)
                        {
                            revCmd = 0;
                            revIndex = 0;
                            sendCmd = 0;
                        }
                        else if (
                            (sendCmd == stscmd && (waitcount == 2 || waitcount == 4))
                            ||
                            (sendCmd == anacmd && (waitcount == 30 || waitcount == 60))
                            ||
                            (sendCmd == powcmd && (waitcount == 2 || waitcount == 4))
                            )
                        {
                            TransmiteFrame(txData, txLength);
                        }
                        else if (waitcount > 80)
                        {
                            revCmd = 0;
                            revIndex = 0;
                            sendCmd = 0;
                        }
                        #endregion
                    }
                    else if (DateTime.Now.Second != mytime.Second)
                    {
                        #region stsFrame send
                        mytime = mytime.AddSeconds(1);
                        textBox2_sourceAddr.Text = "20";
                        textBox3_targetAddr.Text = "60";
                        textBox4_type.Text = "01";
                        textBox5_CMD.Text = stsCMD;
                        textBox6_data.Text = "88 00 DC 02 00 00 02 01 00";
                        PrepareData(true);
                        sendCmd = txData[5];
                        stsIndex++;
                        txData[6] = (byte)(stsIndex & 0xff);
                        txData[7] = (byte)(stsIndex >> 8);

                        TransmiteFrame(txData, txLength);
                        #endregion
                    }
                    else if (anaSize > 0)
                    {
                        #region anaFrame send
                        const int MAXLEN = 0x1000;
                        const int FLEN = 183 * 1024;
                        int offset = 0;
                        textBox2_sourceAddr.Text = "20";
                        textBox3_targetAddr.Text = "60";
                        textBox4_type.Text = "01";
                        textBox5_CMD.Text = anaCMD;
                        int count = anaSize % FLEN;
                        count = FLEN - count;
                        count = count % FLEN;
                        count = count / MAXLEN;
                        count = count % 128;

                        textBox6_data.Text = "88 00 DC 02 00 00 02 01 " + count.ToString("X2") +" 00 00 ";
                        PrepareData(false);
                        
                        sendCmd = txData[5];
                        anaIndex++;
                        txData[6] = (byte)(anaIndex & 0xff);
                        txData[7] = (byte)(anaIndex >> 8);
                        //6 + 8 + 3 + SIZE(MAXLEN)
                        offset = 17;
                        for (int i = 0; i < MAXLEN; i++)
                        {
                            txData[offset + i] = (byte)i;
                        }
                        if ((anaSize % FLEN) == 0)
                        {
                            txData[offset + 0] = 0;
                            txData[offset + 1] = 0;

                            txData[offset + 2] = 0X82;
                            txData[offset + 3] = 0X61;
                            txData[offset + 4] = 0X51;
                            txData[offset + 5] = 0X41;
                            
                            uint time = (uint)(
                            ((anaTime[1].Year - 2000) << 26) |
                            (anaTime[1].Month << 22) |
                            (anaTime[1].Day << 17) |
                            (anaTime[1].Hour << 12) |
                            (anaTime[1].Minute << 06) |
                            (anaTime[1].Second << 0));
                            txData[offset + 6] = (byte)(time >> 0);
                            txData[offset + 7] = (byte)(time >> 8);
                            txData[offset + 8] = (byte)(time >> 16);
                            txData[offset + 9] = (byte)(time >> 24);

                            for (int i = 1; i < (byte)(anaSize / FLEN); i++)
                            {
                                anaTime[i] = anaTime[i + 1];
                            }

                            txData[offset + 10] = 0;
                            txData[offset + 11] = 0;
                            txData[offset + 12] = 0;
                            txData[offset + 13] = 0;
                            txData[offset + 14] = 0X7D;
                            txData[offset + 15] = 0;
                        }
                        if ((anaSize % FLEN) > MAXLEN || (anaSize % FLEN) == 0)
                        {
                            txLength = (int)(offset + MAXLEN);
                            anaSize = anaSize - MAXLEN;
                        }
                        else
                        {
                            txLength = (int)(offset + (anaSize % FLEN));
                            anaSize = anaSize - (anaSize % FLEN);
                        }
                        TransmiteFrame(txData, txLength);
                        #endregion
                    }
                    else if (powSize > 0)
                    {
                        #region powFrame send
                        textBox2_sourceAddr.Text = "20";
                        textBox3_targetAddr.Text = "60";
                        textBox4_type.Text = "01";
                        textBox5_CMD.Text = "F0";
                        textBox6_data.Text = "88 00 DC 02 00 00 00 00";
                        checkBox_STS.Checked = false;
                        PrepareData(true);
                        checkBox_STS.Checked = true;

                        sendCmd = txData[5];
                        powIndex++;
                        txData[6] = (byte)(powIndex & 0xff);
                        txData[7] = (byte)(powIndex >> 8);
                        //6 + 8 + SIZE(64 * 16)
                        for (int i = 0; i < 64; i++)
                        {
                            uint time = (uint)(
                            ((DateTime.Now.Year - 2000) << 26) |
                            (DateTime.Now.Month << 22) |
                            (DateTime.Now.Day << 17) |
                            (DateTime.Now.Hour << 12) |
                            (DateTime.Now.Minute << 06) |
                            (DateTime.Now.Second << 0));
                            txData[14 + 16 * i + 0] = (byte)(time >> 0);
                            txData[14 + 16 * i + 1] = (byte)(time >> 8);
                            txData[14 + 16 * i + 2] = (byte)(time >> 16);
                            txData[14 + 16 * i + 3] = (byte)(time >> 24);

                            txData[14 + 16 * i + 4] = (byte)(kilometerPost >> 0);
                            txData[14 + 16 * i + 5] = (byte)(kilometerPost >> 8);
                            txData[14 + 16 * i + 6] = (byte)(kilometerPost >> 16);

                            txData[14 + 16 * i + 7] = 60;
                            txData[14 + 16 * i + 8] = 30;
                            txData[14 + 16 * i + 9] = 10;
                            txData[14 + 16 * i + 10] = 8;
                            txData[14 + 16 * i + 11] = 7;
                            txData[14 + 16 * i + 12] = 6;
                            txData[14 + 16 * i + 13] = 5;
                            txData[14 + 16 * i + 14] = 4;
                            txData[14 + 16 * i + 15] = 4;
                        }
                        if (powSize > 64 * 16)
                        {
                            txLength = (int)(14 + 64*16);
                            powSize = powSize - 64 * 16;
                        }
                        else
                        {
                            txLength = (int)(14 + powSize);
                            powSize = 0;
                        }
                        TransmiteFrame(txData, txLength);
                        #endregion
                    }

                }
                
            }
            
        }
        #endregion

        #region calculator
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            FormValCal formVal = new FormValCal();
            formVal.Owner = this;
            formVal.Show();
            frameManager.AddFilter(new ValCalFilter(formVal));
        }
        #endregion


        #region filter
        class FrameFilter : IFrameFilter
        {


            FormMain form;

            public FrameFilter(FormMain form)
            {
                this.form = form;
            }

            #region IFrameFilter 成员

            public bool Match(Frame frame)
            {
                return true;
            }

            public void AddFrame(Frame frame)
            {
                this.form.ShowFrame(frame);
            }

            public Frame GetFrame(int timeout)
            {
                return null;
            }

            #endregion
        }


        class ValCalFilter : IFrameFilter
        {

            FormValCal form;
            public ValCalFilter(FormValCal form)
            {
                this.form = form;
            }

            #region IFrameFilter 成员

            public bool Match(Frame frame)
            {
                return true;
            }

            public void AddFrame(Frame frame)
            {
                if (this.form != null && (this.form.IsDisposed == false))
                {
                    form.CalFrame(frame);
                }
            }

            public Frame GetFrame(int timeout)
            {
                return null;
            }

            #endregion
        }
        #endregion

        

        

        

        

        

        


 


        

        

        

       

        
    }
}
